import { extend, trim, merge, includes, map } from "lodash";
import React, {useEffect, useState } from "react";
import PropTypes from "prop-types";
import { compact, isEmpty, invoke } from "lodash";
import { markdown } from "markdown";
import cx from "classnames";
import Menu from "antd/lib/menu";
import Radio from 'antd/lib/radio';
import Breadcrumb from 'antd/lib/breadcrumb';
import Dropdown from "antd/lib/dropdown";
import Button from "antd/lib/button";
import HtmlContent from "@redash/viz/lib/components/HtmlContent";
import { Auth, currentUser } from "@/services/auth";
import recordEvent from "@/services/recordEvent";
import { formatDateTime } from "@/lib/utils";
import Link from "@/components/Link";
import Parameters from "@/components/Parameters";
import TimeAgo from "@/components/TimeAgo";
import Timer from "@/components/Timer";
import { Moment } from "@/components/proptypes";
import QueryLink from "@/components/QueryLink";
import { FiltersType } from "@/components/Filters";
import ExpandedWidgetDialog from "@/components/dashboards/ExpandedWidgetDialog";
import ExpandedDashboardDialog from "@/components/dashboards/ExpandedDashboardDialog";
import ExpandedUrlDialog from "@/components/dashboards/ExpandedUrlDialog";
import QueryResultsLink from "@/components/EditVisualizationButton/QueryResultsLink";
import EditParameterMappingsDialog from "@/components/dashboards/EditParameterMappingsDialog";
import VisualizationRenderer from "@/components/visualizations/VisualizationRenderer";
import Widget from "./Widget";
import { DownOutlined  } from '@ant-design/icons';
import  * as Icons from '@ant-design/icons';
import { replaceUrlParameter } from "@redash/viz/lib/lib/DateRangeParameter";
import location from "@/services/location";
import { policy } from "@/services/policy";
import DataSource from "@/services/data-source";
import Upload from "antd/lib/upload";
import message from 'antd/lib/message';
import notification from "@/services/notification";
import { axios } from "@/services/axios";

import "./VisualizationWidget.less";

function visualizationWidgetMenuOptions({ widget, canEditDashboard, onParametersEdit, widgetHidePopMenus, isContainer, dataSource }) {
  const canViewQuery = currentUser.hasPermission("view_query");
  const canEditParameters = canEditDashboard && !isEmpty(invoke(widget, "query.getParametersDefs"));
  const widgetQueryResult = widget.getQueryResult();
  const isQueryResultEmpty = !widgetQueryResult || !widgetQueryResult.isEmpty || widgetQueryResult.isEmpty();

  const downloadLink = fileType => widgetQueryResult.getLink(widget.getQuery().id, fileType);
  const downloadName = fileType => widgetQueryResult.getName(widget.getQuery().name, fileType);

  const showPortal = window.location.search.includes("show_portal") && localStorage.getItem('colorstyle_mode');

  const uploadProps = dataSource && {
    name: 'file',
    showUploadList: false,
    accept: dataSource.type === 'excel' ? ".xls,.xlsx" : dataSource.type,
    action: 'api/queries/' + dataSource.id + '/upload/' + widget.query_id,
    maxCount:1,
    headers: {
      authorization: 'authorization-text',
    },
    onChange(info) {
      if (info.file.status !== 'uploading') {
        window.console.log(info.file, info.fileList);
      }
      if (info.file.status === 'done') {
        message.success(`${info.file.name} 文件上传成功！`);
        setTimeout(()=>{
          window.location.reload();          
        }, 2000);
      } else if (info.file.status === 'error') {
        message.error(`${info.file.name} 文件上传失败！可能没有当前数据源权限，请联系系统管理员`);
      }
    },
  };  

  return compact([
    !widgetHidePopMenus && (
    <Menu.Item key="download_csv" disabled={isQueryResultEmpty}>
      {isQueryResultEmpty ? ("另存为CSV文件") : (
        Auth.getApiKey() ? (
          <QueryResultsLink
          fileType="csv"
          query={widget.getQuery()}
          queryResult={widgetQueryResult}
          apiKey={Auth.getApiKey()}
          disabled={!widgetQueryResult || !widgetQueryResult.getData || !widgetQueryResult.getData()}
          embed>
          另存为CSV文件
        </QueryResultsLink>) : (
        <Link href={downloadLink("csv")} download={downloadName("csv")} target="_self">
          另存为CSV文件
        </Link>)
      )}
    </Menu.Item>),
    !widgetHidePopMenus && (
    <Menu.Item key="download_tsv" disabled={isQueryResultEmpty}>
      {isQueryResultEmpty ? ("另存为TSV文件") : (
        Auth.getApiKey() ? (
          <QueryResultsLink
          fileType="tsv"
          query={widget.getQuery()}
          queryResult={widgetQueryResult}
          apiKey={Auth.getApiKey()}
          disabled={!widgetQueryResult || !widgetQueryResult.getData || !widgetQueryResult.getData()}
          embed>
          另存为TSV文件
        </QueryResultsLink>) : (
        <Link href={downloadLink("tsv")} download={downloadName("tsv")} target="_self">
          另存为TSV文件
        </Link>)
      )}
    </Menu.Item>),
    !widgetHidePopMenus && (
    <Menu.Item key="download_excel" disabled={isQueryResultEmpty}>
      {isQueryResultEmpty ? ("另存为Excel文件") : (
        Auth.getApiKey() ? (
          <QueryResultsLink
          fileType="xlsx"
          query={widget.getQuery()}
          queryResult={widgetQueryResult}
          apiKey={Auth.getApiKey()}
          disabled={!widgetQueryResult || !widgetQueryResult.getData || !widgetQueryResult.getData()}
          embed>
          另存为Excel文件
        </QueryResultsLink>) : (
        <Link href={downloadLink("xlsx")} download={downloadName("xlsx")} target="_self">
          另存为Excel文件
        </Link>)
      )}
    </Menu.Item>),
    !widgetHidePopMenus && !Auth.getApiKey() && dataSource && (dataSource.type === 'json' || dataSource.type === 'csv' || dataSource.type === 'excel') && (
    <>
    <Menu.Divider key="divider_load" />
    {!isQueryResultEmpty && (
      <Menu.Item key="download_excel">
        <Link href={'api/queries/download/' + widget.query_id} download={downloadName("xlsx")} target="_self">
          下载数据源文件
        </Link>
      </Menu.Item>
      )}
    <Menu.Item key="upload_excel">
      <Upload {...uploadProps}>
        <Button size='small'>上传文件更新数据源</Button>
      </Upload>
    </Menu.Item>
    </>),
    !showPortal && !isContainer && (canViewQuery || canEditParameters) && <Menu.Divider key="divider" />,
    !showPortal && !isContainer && canViewQuery && (
      <Menu.Item key="view_query">
        <Link href={widget.getQuery().getUrl(true, widget.visualization.id)}>查看查询定义</Link>
      </Menu.Item>
    ),
    !showPortal && !isContainer && canEditParameters && (
      <Menu.Item key="edit_parameters" onClick={onParametersEdit}>
        编辑参数
      </Menu.Item>
    ),
  ]);
}

function RefreshIndicator({ refreshStartedAt }) {
  return (
    <div className="refresh-indicator" style={{background: "#00000000", color: localStorage.getItem("colorstyle_titlecolor")}}>
      <div className="refresh-icon">
        <i className="zmdi zmdi-refresh zmdi-hc-spin" />
      </div>
      <Timer from={refreshStartedAt} />
    </div>
  );
}

RefreshIndicator.propTypes = { refreshStartedAt: Moment };
RefreshIndicator.defaultProps = { refreshStartedAt: null };

function VisualizationWidgetHeader({ widget, refreshStartedAt, parameters, onParametersUpdate, dashboardOptions, onRefresh, isContainer }) {
  const canViewQuery = currentUser.hasPermission("view_query");
  const isShowFilters = !widget.getWidgetOptions("hide_parameters");
  const showPortal = window.location.search.includes("show_portal") && localStorage.getItem('colorstyle_mode');
  const portalstyle = showPortal ? localStorage.getItem('colorstyle_mode') : 'portal';
  //const refreshRate = window.location.search.includes("refresh") 
  const widgetBgTransparent = !!widget.getWidgetOptions("widget_image") || widget.getWidgetOptions("widget_bg") ? true : widget.getWidgetOptions("widget_bgtransparent"); 
  const isTitleBg = widget.getWidgetOptions("title_bg"); 
  const widgetTitleBg = isTitleBg ? 'url(' + policy.getHost() + '/static/images/' + portalstyle + '/titlebg.png) no-repeat center' : (!!widget.getWidgetOptions("widget_titlebg") ? widget.getWidgetOptions("widget_titlebg") : null); 



  const refreshRate=dashboardOptions.refreshRate;
  const no_refresh= widget.options.widgetOptions.no_refresh;
//=================================20221022===

  useEffect(() => {
    //去掉报表自动刷新20221022
    if(showPortal && refreshRate && ! no_refresh){
      window.console.log('this.propssetInterval',no_refresh);
        const refreshTimer = setInterval(() => {
              dashboardOptions.refreshWidget(widget);
              dashboardOptions.refreshWidget(widget, 0, false);
             }, refreshRate * 1000);
         return () => clearInterval(refreshTimer);
    }
  }, [refreshRate]);// eslint-disable-line react-hooks/exhaustive-deps
  //=============================end=============



  const muiltView = (widget.getWidgetOptions("toggle_view1") && widget.getWidgetOptions("toggle_view1") instanceof Object)
    || (widget.getWidgetOptions("toggle_view2") && widget.getWidgetOptions("toggle_view2") instanceof Object)
    || (widget.getWidgetOptions("toggle_view3") && widget.getWidgetOptions("toggle_view3") instanceof Object)
    || (widget.getWidgetOptions("toggle_view4") && widget.getWidgetOptions("toggle_view4") instanceof Object)
    || (widget.getWidgetOptions("toggle_view5") && widget.getWidgetOptions("toggle_view5") instanceof Object)

  var is_bread = false;
  var nextviewid = 0;
  const cssStyle = {
    "--style-color": localStorage.getItem("colorstyle_color"),
  }
  const auto =  muiltView && widget.getWidgetOptions("toggle_view_style") === "Auto" && ( 
    <Breadcrumb separator=">" style={showPortal ? cssStyle : null}>
      {["1","2","3","4","5"].map(item => {
        const newIcon = Icons[widget.getWidgetOptions("toggle_view"  + item + "_icon")];
        if (widget.getWidgetOptions("toggle_view" + item) && widget.getWidgetOptions("toggle_view" + item) instanceof Object) {
          if (is_bread) {
            nextviewid = parseInt(widget.getWidgetOptions("toggle_view" + item).id);
            is_bread = false;
          }
          if (nextviewid === 0) {
            nextviewid = parseInt(widget.getWidgetOptions("toggle_view" + item).id);
          }
          if (parseInt(widget.getWidgetOptions("toggle_view" + item).id) === widget.visualization.id) {
            is_bread = true;
          }
        } 

        item === "5" && setTimeout(() => {
          onRefresh(nextviewid);
          dashboardOptions.refreshWidget(widget);
        }, 3000);
              
        return widget.getWidgetOptions("toggle_view" + item) && widget.getWidgetOptions("toggle_view" + item) instanceof Object && ( 
          parseInt(widget.getWidgetOptions("toggle_view" + item).id) === widget.visualization.id ? (
            <Breadcrumb.Item key={widget.getWidgetOptions("toggle_view" + item).id}>
            {newIcon && React.createElement(newIcon)}
            <span>{widget.getWidgetOptions("toggle_view" + item + "_title") || "菜单" + item}</span>
            </Breadcrumb.Item>
          ) : null
        );}
      )}
    </Breadcrumb>
  );

  const bread =  muiltView && widget.getWidgetOptions("toggle_view_style") === "Bread" && ( 
    <Breadcrumb separator=">" style={showPortal ? cssStyle : null}>
      {["1","2","3","4","5"].map(item => {
        const newIcon = Icons[widget.getWidgetOptions("toggle_view"  + item + "_icon")];
        if (widget.getWidgetOptions("toggle_view" + item) && widget.getWidgetOptions("toggle_view" + item) instanceof Object) {
          if (parseInt(widget.getWidgetOptions("toggle_view" + item).id) === widget.visualization.id) {
            is_bread = true;
          }
        } 
        
        return widget.getWidgetOptions("toggle_view" + item) && widget.getWidgetOptions("toggle_view" + item) instanceof Object && ( 
          parseInt(widget.getWidgetOptions("toggle_view" + item).id) === widget.visualization.id ? (
            <Breadcrumb.Item key={widget.getWidgetOptions("toggle_view" + item).id}>
            {newIcon && React.createElement(newIcon)}
            <span>{widget.getWidgetOptions("toggle_view" + item + "_title") || "菜单" + item}</span>
            </Breadcrumb.Item>
          ) : (is_bread ? null : ( 
            <Breadcrumb.Item href key={widget.getWidgetOptions("toggle_view" + item).id} onClick={e => onRefresh(parseInt(widget.getWidgetOptions("toggle_view" + item).id))}>
            {newIcon && React.createElement(newIcon)}
            <span>{widget.getWidgetOptions("toggle_view" + item + "_title") || "菜单" + item}</span>
            </Breadcrumb.Item>)
          )   
        );}
      )}
    </Breadcrumb>
  );

  const menu =  muiltView && (widget.getWidgetOptions("toggle_view_style") === "Radio" ? (
    <Radio.Group value={widget.visualization.id} buttonStyle="outline"
      onChange={e => onRefresh(parseInt(e.target.value))}
    >
      {["1","2","3","4","5"].map(item => {
        const newIcon = Icons[widget.getWidgetOptions("toggle_view"  + item + "_icon")];
        return widget.getWidgetOptions("toggle_view" + item) && widget.getWidgetOptions("toggle_view" + item) instanceof Object && (    
          <Radio.Button value={widget.getWidgetOptions("toggle_view" + item).id}
            style={showPortal ? {backgroundColor: "#00000000", color: localStorage.getItem("colorstyle_color")} : null}
          >
            {newIcon && React.createElement(newIcon)}
            {widget.getWidgetOptions("toggle_view" + item + "_title") || "菜单" + item}
          </Radio.Button>
        );}
      )}
    </Radio.Group>
  ):(
    <Menu className='widget-menu' selectedKeys={[widget.visualization.id.toString()]} 
      onClick={e => onRefresh(parseInt(e.key))}
      style={showPortal && widget.getWidgetOptions("toggle_view_style") === "Menu" ? {background: "#00000000", color: localStorage.getItem('colorstyle_titlecolor')} : null}
      mode={widget.getWidgetOptions("toggle_view_style") === "Menu" ? "horizontal" : "vertical"}
    >
    {["1","2","3","4","5"].map(item => {
      const newIcon = Icons[widget.getWidgetOptions("toggle_view"  + item + "_icon")];
      return widget.getWidgetOptions("toggle_view" + item) && widget.getWidgetOptions("toggle_view" + item) instanceof Object && (    
        <Menu.Item key={widget.getWidgetOptions("toggle_view" + item).id}>
          {newIcon && React.createElement(newIcon)}
          {widget.getWidgetOptions("toggle_view" + item + "_title") || "菜单" + item}
        </Menu.Item>
      );}
    )}
    </Menu>
  ));

  var title = replaceUrlParameter(widget.getWidgetOptions("widget_title"));
  var show_title = !widget.getWidgetOptions("hide_header");
  if (!show_title && (auto || bread || menu)) {
    title = ' ';
    show_title = true;
  }

  var mdcss = {}
  if (showPortal) merge(mdcss, {color: localStorage.getItem('colorstyle_titlecolor')});
  if (!!widget.getWidgetOptions("title_center")) merge(mdcss, {textAlign:'center'});

  return (
    <>
      <RefreshIndicator refreshStartedAt={refreshStartedAt} />
      {show_title && (
        <div className="t-header widget clearfix"
          style={widgetTitleBg ? {
            background: widgetTitleBg,
            color: localStorage.getItem('colorstyle_titlecolor'),
            height: '40px',
            padding: !!widget.getWidgetOptions("title_center") && !!title && widget.getWidgetOptions("showDescription") && (!isEmpty(widget.getQuery().description) || !isEmpty(widget.getWidgetOptions("widget_description"))) ? '4px' : '12px',
          } : (showPortal ? {
            background: ((isContainer || widgetBgTransparent || !!widget.getWidgetOptions("hide_header")) ? 'transparent' : localStorage.getItem('colorstyle_titleback')), 
            color: localStorage.getItem('colorstyle_titlecolor'),
            height: '40px',
            padding: !!widget.getWidgetOptions("title_center") && !!title && widget.getWidgetOptions("showDescription") && (!isEmpty(widget.getQuery().description) || !isEmpty(widget.getWidgetOptions("widget_description"))) ? '4px' : '12px',
          } : {
            height: '40px',
            padding: !!widget.getWidgetOptions("title_center") && !!title && widget.getWidgetOptions("showDescription") && (!isEmpty(widget.getQuery().description) || !isEmpty(widget.getWidgetOptions("widget_description"))) ? '4px' : '12px',
          })}
        >
        <div className="th-title">
            {!!title && trim(title)==='' ? (
              <div style={{float:'left', marginTop: '-7px'}}>
              {widget.getWidgetOptions("toggle_view_style") === "Auto" && auto}
              {widget.getWidgetOptions("toggle_view_style") === "Bread" && bread}
              {widget.getWidgetOptions("toggle_view_style") === "Radio" && menu}
              {widget.getWidgetOptions("toggle_view_style") === "Menu" && menu}
              {menu && (!widget.getWidgetOptions("toggle_view_style") || widget.getWidgetOptions("toggle_view_style") === "Dropdown") && (
                <Dropdown overlay={menu}>
                <Button style={showPortal ? {color: localStorage.getItem('colorstyle_titlecolor')} : null}>
                  {widget.getWidgetOptions("toggle_view_title") || "请选择"} <DownOutlined  />
                </Button>
                </Dropdown>
              )}
              </div>
            ) : (
              <React.Fragment>
              {!isEmpty(parameters) && isShowFilters && !!widget.getWidgetOptions("title_parameter") && !!widget.getWidgetOptions("title_center") && (
                <div style={showPortal ? {background: "#00000000", float: 'left', marginTop: '-11px'} : {float: 'left', marginTop: '-11px'}}>
                  <Parameters parameters={parameters}  onValuesChange={onParametersUpdate} />
                </div>
              )}
              <div style={!!widget.getWidgetOptions("title_center") && !widget.getWidgetOptions("title_parameter") ? {textAlign:'center',float: 'middle'} : {float: 'left'}}>
                {!!title ? (
                  <span style={showPortal ? {color: localStorage.getItem('colorstyle_titlecolor'), fontWeight: 600} : null}>
                    <HtmlContent>{title}</HtmlContent>
                  </span>
                  ) : (
            <QueryLink query={widget.getQuery()} visualization={widget.visualization} readOnly={!canViewQuery} />
                )}
              </div>
              {!isEmpty(parameters) && isShowFilters && !!widget.getWidgetOptions("title_parameter") && !widget.getWidgetOptions("title_center") && (
                <div style={showPortal ? {background: "#00000000", marginTop:'-11px', float: 'left'} : {marginTop:'-11px', float: 'left'}}>
                  <Parameters parameters={parameters}  onValuesChange={onParametersUpdate} />
                </div>
              )}
              <div style={{float:'right', marginRight:'60px', marginTop: !!widget.getWidgetOptions("title_center") && !widget.getWidgetOptions("title_parameter") ? '-25px' : '-8px'}}>
                {widget.getWidgetOptions("toggle_view_style") === "Bread" && bread}
                {widget.getWidgetOptions("toggle_view_style") === "Radio" && menu}
                {widget.getWidgetOptions("toggle_view_style") === "Menu" && menu}
                {menu && (!widget.getWidgetOptions("toggle_view_style") || widget.getWidgetOptions("toggle_view_style") === "Dropdown") && (
                  <Dropdown overlay={menu}>
                  <Button style={showPortal ? {color: localStorage.getItem('colorstyle_titlecolor')} : null}>
                    {widget.getWidgetOptions("toggle_view_title") || "请选择"} <DownOutlined  />
                  </Button>
                  </Dropdown>
                )}
              </div>
              </React.Fragment>
            )}

            {widget.getWidgetOptions("showDescription") && (!isEmpty(widget.getQuery().description) || !isEmpty(widget.getWidgetOptions("widget_description"))) && (
              <div>
                <HtmlContent className="text-muted markdown query--description" style={mdcss}>
                {markdown.toHTML(widget.getWidgetOptions("widget_description") || widget.getQuery().description || "")}
            </HtmlContent>
              </div>
          )}
        </div>
      </div>
      )}
      {!isEmpty(parameters) && isShowFilters && (!widget.getWidgetOptions("title_parameter") || !show_title || (!!title && trim(title)==='')) && (
        <div className="m-b-10" style={showPortal ? {background: "#00000000", marginTop:'8px'} : {marginTop:'8px'}}>
          <Parameters parameters={parameters}  onValuesChange={onParametersUpdate} />
        </div>
      )}
    </>
  );
}

VisualizationWidgetHeader.propTypes = {
  widget: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
  refreshStartedAt: Moment,
  parameters: PropTypes.arrayOf(PropTypes.object),
  onParametersUpdate: PropTypes.func,
  onRefresh: PropTypes.func,
  isContainer: PropTypes.bool,
};

VisualizationWidgetHeader.defaultProps = {
  refreshStartedAt: null,
  onParametersUpdate: () => {},
  parameters: [],
  isContainer: false,
};

function VisualizationWidgetFooter({ widget, isPublic, onRefresh, onExpand }) {
  const widgetQueryResult = widget.getQueryResult();
  const updatedAt = invoke(widgetQueryResult, "getUpdatedAt");
  const [refreshClickButtonId, setRefreshClickButtonId] = useState();
  const showPortal = window.location.search.includes("show_portal") && localStorage.getItem('colorstyle_mode');

  const refreshWidget = buttonId => {
    if (!refreshClickButtonId) {
      setRefreshClickButtonId(buttonId);
      onRefresh(0).finally(() => setRefreshClickButtonId(null));
    }
  };

  return widgetQueryResult && !widget.getWidgetOptions("hide_timestamp") ? (
    <>
      <span>
        {!isPublic && !!widgetQueryResult && (
          <a
            className="refresh-button hidden-print btn btn-sm btn-default btn-transparent"
            onClick={() => refreshWidget(1)}
            style={showPortal ? {color: localStorage.getItem('colorstyle_color')} : null}
            data-test="RefreshButton">
            <i className={cx("zmdi zmdi-refresh", { "zmdi-hc-spin": refreshClickButtonId === 1 })} />{" "}
            <TimeAgo date={updatedAt} />
          </a>
        )}
        <span className="visible-print" style={showPortal ? {color: localStorage.getItem('colorstyle_color')} : null}>
          <i className="zmdi zmdi-time-restore" /> {formatDateTime(updatedAt)}
        </span>
        {isPublic && (
          <span className="small hidden-print" style={showPortal ? {color: localStorage.getItem('colorstyle_color')} : null}>
            <i className="zmdi zmdi-time-restore" /> <TimeAgo date={updatedAt} />
          </span>
        )}
      </span>
      <span>
        {!isPublic && (
          <a
            className="btn btn-sm btn-default hidden-print btn-transparent btn__refresh"
            onClick={() => refreshWidget(2)}>
            <i className={cx("zmdi zmdi-refresh", { "zmdi-hc-spin": refreshClickButtonId === 2 })} />
          </a>
        )}
        <a className="btn btn-sm btn-default hidden-print btn-transparent btn__refresh" onClick={onExpand}>
          <i className="zmdi zmdi-fullscreen" />
        </a>
      </span>
    </>
  ) : null;
}

VisualizationWidgetFooter.propTypes = {
  widget: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
  isPublic: PropTypes.bool,
  onRefresh: PropTypes.func,
  onExpand: PropTypes.func.isRequired,
};

VisualizationWidgetFooter.defaultProps = { isPublic: false };

class VisualizationWidget extends React.Component {
  static propTypes = {
    widget: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
    dashboard: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
    dashboardOptions: PropTypes.object.isRequired,
    filters: FiltersType,
    isPublic: PropTypes.bool,
    isLoading: PropTypes.bool,
    canEdit: PropTypes.bool,
    onLoad: PropTypes.func,
    onRefresh: PropTypes.func,
    onDelete: PropTypes.func,
    onParameterMappingsChange: PropTypes.func,
    widgetMargins: PropTypes.number,
    widgetRadius: PropTypes.number,
    scale: PropTypes.number,
    scaleX: PropTypes.number,
    isContainer: PropTypes.bool,
  };

  static defaultProps = {
    filters: [],
    isPublic: false,
    isLoading: false,
    canEdit: false,
    onLoad: () => {},
    onRefresh: () => {},
    onDelete: () => {},
    onParameterMappingsChange: () => {},
    widgetMargins: -1,
    widgetRadius: -1,
    scale: 1,
    scaleX: 1,
    isContainer: false,
  };

  constructor(props) {
    super(props);
    this.state = {
      localQuery: props.widget.query_id, 
      localParameters: props.widget.getLocalParameters(),
      localFilters: props.filters,
      dataSource: null,
    };
  }

  componentDidUpdate() {
    const { widget } = this.props;
    if (widget.type !== "textbox") {
      //非常重要，若不加href随机数，则不会刷新
      if (window.location.search.includes("show_widgetdialog") && parseInt(location.search.show_widgetdialog) === widget.id) {
        location.setSearch({show_widgetdialog:null}, true);
        location.setPath(location.path + "-" + Math.ceil(Math.random()*10000),true);
        this.expandDashboard();
      } else if (window.location.search.includes("show_clickdialog") && parseInt(location.search.show_clickdialog) === widget.id) {
        location.setSearch({show_clickdialog:null}, true);
        location.setPath(location.path + "-" + Math.ceil(Math.random()*10000),true);
        this.expandClickDashboard();
      }
    }
  }

  componentWillMount() {
    const { widget, isPublic } = this.props;
    if (!isPublic) {
      const data_source_id = widget.getQuery().data_source_id;
      DataSource.get({ id: data_source_id }).then(dataSource =>{
        this.setState({ dataSource });
      });
    }
  }

  componentDidMount() {
    const { widget, onLoad } = this.props;
    recordEvent("view", "query", widget.visualization.query.id, { dashboard: true });
    recordEvent("view", "visualization", widget.visualization.id, { dashboard: true });
    onLoad();
  }

  onLocalFiltersChange = localFilters => {
    this.setState({ localFilters });
  };

  expandWidget = () => {
    ExpandedWidgetDialog.showModal({ widget: this.props.widget, filters: this.state.localFilters });
  };

  expandDashboardCode = (dashboardId=null, isClick=false) => {
    const { widget, isPublic} = this.props;

    ExpandedDashboardDialog.showModal({ widget, 
      dashboardId: dashboardId || (isClick ? widget.getWidgetOptions("clickdashboard_id") : widget.getWidgetOptions("dashboard_id")), 
      popClickCheck: isClick ? 1 : 0, isPublic
    });
  };

  expandDashboard = () => {
    const { widget, dashboardOptions } = this.props;
    var url = widget.getWidgetOptions("pop_url") || widget.getWidgetOptions("pop_title");
    if (url) url = replaceUrlParameter(url);

    if (widget.getWidgetOptions("dashboard_id") === "HREF") {
      window.location.href = url;
    } else if (widget.getWidgetOptions("dashboard_id") === "URL") {
      window.open(url, !!widget.getWidgetOptions("pop_urlblank") ? "_blank" : "pop_dazdata", widget.getWidgetOptions("pop_width"));
    } else if (widget.getWidgetOptions("dashboard_id") === "POP") {
      const pop_width = widget.getWidgetOptions("pop_width");
      const pop_height = widget.getWidgetOptions("pop_height");
      const width = !!pop_width ? pop_width : "80%";
      const height = !!pop_height ? pop_height : "480px";
      const title = widget.getWidgetOptions("pop_title");
      const refresh = widget.getWidgetOptions("pop_refresh");

      ExpandedUrlDialog.showModal({ width, height, title, url, refresh});
    } else {
      const refresh = widget.getWidgetOptions("pop_refresh");
      if (!!url) {
        const params = extend({}, location.search);
        var objurls = {};
        map(url.split('&'), item => {
          const key = item.split('=')[0]
          const value = item.split('=')[1]
          objurls["p_" + key] = value;
        });
        extend(params, objurls);
        location.setSearch(params, true);
      }
      ExpandedDashboardDialog.showModal({ widget: this.props.widget, 
        dashboardId: widget.getWidgetOptions("dashboard_id"), 
        popClickCheck: 0, isPublic: this.props.isPublic, refresh
      }).onClose(()=>{
        if (!!refresh) dashboardOptions.refreshDashboard(true);
      })
    }
  };

  expandClickDashboard = (keyValues=null) => {
    const { widget, dashboardOptions, onRefresh } = this.props;
    if (!!!widget.getWidgetOptions("clickdashboard_id")) return;
    var url = widget.getWidgetOptions("click_url") || widget.getWidgetOptions("click_title");

    if (url && includes(["HREF","URL","POP"], widget.getWidgetOptions("clickdashboard_id"))) {
      if (keyValues) {
        const params = extend({}, location.search);
        var objurls = {};
        Object.keys(keyValues).forEach(function(key){
          objurls["p_" + key] = keyValues[key];
        });
        extend(params, objurls);
        location.setSearch(params, true);
      }
      url = replaceUrlParameter(url);
    }

    if (widget.getWidgetOptions("clickdashboard_id") === "HREF") {
      window.location.href = url;
    } else if (widget.getWidgetOptions("clickdashboard_id") === "URL") {
      window.open(url, !!widget.getWidgetOptions("click_urlblank") ? "_blank" : "pop_dazdata", widget.getWidgetOptions("click_width"));
    } else if (widget.getWidgetOptions("clickdashboard_id") === "POP") {
      const pop_width = widget.getWidgetOptions("click_width");
      const pop_height = widget.getWidgetOptions("click_height");
      const width = !!pop_width ? pop_width : "80%";
      const height = !!pop_height ? pop_height : "480px";
      const title = widget.getWidgetOptions("click_title");
      const refresh = widget.getWidgetOptions("click_refresh");

      ExpandedUrlDialog.showModal({ width, height, title, url, refresh});
    } else if (widget.getWidgetOptions("clickdashboard_id") === "VIEWS") {
      if (keyValues) {
        const params = extend({}, location.search);
        var objviews = {};
        Object.keys(keyValues).forEach(function(key){
          objviews["p_w" + widget.id +"_" + key] = keyValues[key];
        });
        extend(params, objviews);
        location.setSearch(params, true);
      }
      if (dashboardOptions) {
        var is_bread = false;
        var nextviewid = 0;
        ["1","2","3","4","5"].map(item => {
          if (widget.getWidgetOptions("toggle_view" + item) && widget.getWidgetOptions("toggle_view" + item) instanceof Object) {
            if (is_bread) {
              nextviewid = parseInt(widget.getWidgetOptions("toggle_view" + item).id);
              is_bread = false;
            }
            if (parseInt(widget.getWidgetOptions("toggle_view" + item).id) === widget.visualization.id) { 
              is_bread = true;
            }
          }
          return null;
        });

        if (nextviewid !== 0) {
          onRefresh(nextviewid);
          dashboardOptions.refreshWidget(widget);
        }
      } 
    } else {
      if (keyValues) {
        const params = extend({}, location.search);
        Object.keys(keyValues).forEach(function(key){
          for (var param in params) {
            if (param.indexOf("p_w") === 0 && param.indexOf("_" + key) > 3) {
              params[param] = keyValues[key];
              let cur_wid = param.split('_')[1];
  
              dashboardOptions.dashboard.widgets.map( wid => {
                if ('w' + wid.id.toString() === cur_wid && wid.query && wid.query.$parameters) {
                  wid.query.$parameters = null;  //解决Table视图单击不刷新问题
                }
                return wid;
              });            
            }
          };
        });

        var obj = {};
        Object.keys(keyValues).forEach(function(key){
          obj["p_" + key] = keyValues[key];
        });
        extend(params, obj);
        location.setSearch(params, true);
        if (widget.query && widget.query.$parameters) {
          widget.query.$parameters = null;  //解决Table视图单击不刷新问题
        }
      }

      if (widget.getWidgetOptions("clickdashboard_id") === "REFRESH" || widget.getWidgetOptions("clickdashboard_id") === "WIDGETS") {
        if (keyValues) {
          var globalParameters = dashboardOptions.globalParameters;
          if (globalParameters && globalParameters.length > 0) {
            var isChange = false;
            globalParameters.forEach(parameter => {
              Object.keys(keyValues).forEach(function(key){
                if (parameter.name === key){
                  parameter.$$value = keyValues[key];
                  parameter.value = keyValues[key];
                  isChange = true
                }
              });      
            });

            if (isChange) {
              // parameter.pendingValue = value;
              dashboardOptions.dashboard.widgets.map( wid => {
                if (wid.query && wid.query.$parameters) {
                  wid.query.$parameters = null;  //解决Table视图单击不刷新问题
                }
                return wid;
              });            
            }
            dashboardOptions.globalParameters = globalParameters;
          }

          var { localParameters } = this.state;
          if (localParameters && localParameters.length > 0) {
            localParameters.forEach(parameter => {
              Object.keys(keyValues).forEach(function(key){
                if (parameter.name === key){
                  parameter.$$value = keyValues[key];
                  parameter.value = keyValues[key];
                  // parameter.pendingValue = value;
                }
              });      
            });
            this.setState({ localParameters: localParameters });
          }
        }  
  
        if (dashboardOptions) {
          if (widget.getWidgetOptions("clickdashboard_id") === "REFRESH") {
            dashboardOptions.refreshDashboard(true);
          } else {
            dashboardOptions.refreshWidget(widget.getWidgetOptions("click_widgets"));
            dashboardOptions.refreshWidget(widget.getWidgetOptions("click_widgets"), 0, false);
          }
        }
      } else {
        const refresh = widget.getWidgetOptions("click_refresh");
        ExpandedDashboardDialog.showModal({ widget: this.props.widget, 
          dashboardId: widget.getWidgetOptions("clickdashboard_id"), 
          popClickCheck: 1, isPublic: this.props.isPublic, refresh 
        }).onClose(()=>{
          if (!!refresh) dashboardOptions.refreshDashboard(true);
        })
      }
    }
  };

  expandCheckDashboard = (selectedRowKeys, clearRowKeys) => {
    const { widget, dashboardOptions } = this.props;
    const refresh = widget.getWidgetOptions("check_refresh");
    if (widget.getWidgetOptions("checkdashboard_id") === "") {
      const url = `api/tablecheckbox/${widget.visualization.id}` 
      axios.post(url, selectedRowKeys).then(w => {
        if (w===true) {
          notification.success("执行成功！");
          if (!!refresh) {
            dashboardOptions.refreshDashboard(true);
            clearRowKeys();
          }
        } else { 
          notification.error("执行失败！" + w);
        }
      }).catch(error => {
        notification.error("执行失败！" + error);
      });  
    } else {
      var url = widget.getWidgetOptions("check_title");
      if (url) url = replaceUrlParameter(url);
      if (!!url) {
        const params = extend({}, location.search);
        var objurls = {};
        map(url.split('&'), item => {
          const key = item.split('=')[0]
          const value = item.split('=')[1]
          objurls["p_" + key] = value;
        });
        extend(params, objurls);
        location.setSearch(params, true);
      }
      localStorage.setItem("selectedRowKeys", selectedRowKeys.toString());
      ExpandedDashboardDialog.showModal({ widget: this.props.widget, 
        dashboardId: widget.getWidgetOptions("checkdashboard_id"), 
        popClickCheck: 2, isPublic: this.props.isPublic, refresh
      }).onClose(()=>{
        if (!!refresh) {
          dashboardOptions.refreshDashboard(true);
          clearRowKeys();
        }
      })
    }
  };

  editParameterMappings = () => {
    const { widget, dashboard, onRefresh, onParameterMappingsChange } = this.props;
    EditParameterMappingsDialog.showModal({
      dashboard,
      widget,
    }).onClose(valuesChanged => {
      // refresh widget if any parameter value has been updated
      if (valuesChanged) {
        onRefresh(0);
      }
      onParameterMappingsChange();
      this.setState({ localParameters: widget.getLocalParameters() });
    });
  };

  renderVisualization() {
    const { widget, filters, scale, scaleX, dashboardOptions } = this.props;
    const widgetQueryResult = widget.getQueryResult();
    const widgetStatus = widgetQueryResult && widgetQueryResult.getStatus();
    const showPortal = window.location.search.includes("show_portal") && localStorage.getItem('colorstyle_mode');
    switch (widgetStatus) {
      case "failed":
        return (
          <div className="body-row-auto scrollbox">
            {!showPortal && widgetQueryResult.getError() && (
              <div className="alert alert-danger m-5" style={showPortal ? {background: "#00000000"} : null}>
                查询运行错误： <strong>{widgetQueryResult.getError()}</strong>
              </div>
            )}
          </div>
        );
      case "done":
        return (widgetQueryResult && widgetQueryResult.query_result.data.rows.length===0 && widget.visualization.type === "TABLE") ? (
          <div 
            className={!!widget.getWidgetOptions("widget_noscroll") ? "body-row-auto noscrollbox": "body-row-auto scrollbox"}
            onClick={!!widget.getWidgetOptions("pop_widget") && this.expandDashboard}
          >
            <div className="alert m-5" style={showPortal ? {background: "#00000000", textAlign: "center"} : {textAlign: "center"}}>
              <img src="static/images/illustrations/no-query-results.svg" alt="查询结果没有记录" />
              <h4 style={showPortal ? {color: localStorage.getItem('colorstyle_color')} : {color: '#000000'}}>查询结果没有记录</h4>
            </div>
          </div>
        ) : (
            <VisualizationRenderer
            visualizations={widget.query.visualizations} 
              visualization={widget.visualization}
              queryResult={widgetQueryResult}
              filters={filters}
              onFiltersChange={this.onLocalFiltersChange}
              context="widget"
            refreshStartedAt={widget.refreshStartedAt}
            onClickHandler={this.expandClickDashboard}
            onCheckHandler={this.expandCheckDashboard}
            onRefreshDashboardHandler={dashboardOptions && dashboardOptions.refreshDashboard}
            onRefreshWidgetHandler={dashboardOptions && dashboardOptions.refreshWidget}
            onExpandDashboardHandler={this.expandDashboardCode}
            scale={scale}
            scaleX={scaleX}
            height={widget.height < (widget.getWidgetOptions("widget_height") || 0) ? widget.getWidgetOptions("widget_height") : null}
            width={widget.width < (widget.getWidgetOptions("widget_width") || 0) ? widget.getWidgetOptions("widget_width") : null}
            widget={widget}
            onWidgetClick={this.expandDashboard}
            />
        )
      default:
        return (
          <div className="body-row-auto spinner-container">
            <div className="spinner">
              <i className="zmdi zmdi-refresh zmdi-hc-spin zmdi-hc-5x" />
            </div>
          </div>
        );
    }
  }

  render() {
    const { widget, isLoading, isPublic, canEdit, dashboardOptions, onRefresh } = this.props;
    const { localParameters } = this.state;
    const widgetQueryResult = widget.getQueryResult();
    const isRefreshing = isLoading && !!(widgetQueryResult && widgetQueryResult.getStatus());
    // 多视图切换重新加载参数
    // var { localQuery, localParameters } = this.state;
    // if (localQuery !== widget.query_id) {
    //   localParameters = widget.getLocalParameters();
    //   this.setState({ 
    //     localQuery: widget.query_id, 
    //     localParameters: localParameters,
    //     localFilters: this.props.filters,
    //   });
    // }

    return (isPublic || this.state.dataSource) && (
      <Widget
        {...this.props}
        className="widget-visualization"
        menuOptions= {visualizationWidgetMenuOptions({
          widget,
          canEditDashboard: canEdit,
          onParametersEdit: this.editParameterMappings,
          widgetHidePopMenus: this.props.widgetHidePopMenus,
          isContainer: this.props.isContainer,
          dataSource: this.state.dataSource,
        })}
        header={
          <VisualizationWidgetHeader
            widget={widget}
            refreshStartedAt={isRefreshing ? widget.refreshStartedAt : null}
            parameters={localParameters}
            onParametersUpdate={onRefresh}
            dashboardOptions={dashboardOptions}
            onRefresh={onRefresh}
            isContainer={this.props.isContainer}
          />
        }
        footer={
          <VisualizationWidgetFooter
            widget={widget}
            isPublic={isPublic}
            onRefresh={onRefresh}
            onExpand={this.expandWidget}
          />
        }
        tileProps={{ "data-refreshing": isRefreshing }}
        showPopButton={!!widget.getWidgetOptions("dashboard_id") ? true : false}
        onExpand={this.expandDashboard}
      >
        {this.renderVisualization()}
      </Widget>
    );
  }
}

export default VisualizationWidget;
